package com.navinf.parkingnavi.util;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PointF;
import android.location.Location;

import androidx.annotation.NonNull;

import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.services.android.navigation.ui.v5.map.NavigationMapboxMap;
import com.navinfo.parkingnavi.R;
import com.navinfo.parkingnavi.util.GsonManager;
import com.navinfo.parkingnavi.util.SystemUtil;
import com.navinfo.parkingnavi.util.mode.Poi;

import java.util.ArrayList;
import java.util.List;

import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOffset;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize;

/*
 *com.navinfo.parkingnavi.util
 *zhjch
 *2020/5/14
 *16:46
 *说明（地图管理）
 */
public class MapManager {
    private MapboxMap mapboxMap;
    private NavigationMapboxMap navigationMapboxMap;
    private Style style;
    private Activity activity;
    private static volatile MapManager mInstance;
    private int mHeight;
    private int mWidth;

    public static MapManager getInstance() {

        if (mInstance == null) {
            synchronized (MapManager.class) {
                if (mInstance == null) {
                    mInstance = new MapManager();
                }
            }
        }
        return mInstance;
    }

    /**
     * 初始化
     *
     * @param activity,
     * @param mapboxMap
     * @param style
     */
    public void init(Activity activity, MapboxMap mapboxMap, NavigationMapboxMap navigationMapboxMap, Style style) {
        this.mapboxMap = mapboxMap;
        this.navigationMapboxMap = navigationMapboxMap;
        this.style = style;
        this.activity = activity;
        mHeight = SystemUtil.getScreenHeight(activity);
        mWidth = SystemUtil.getScreenWidth(activity);
    }

    /**
     * 返回导航地图
     *
     * @return
     */
    public NavigationMapboxMap getNavigationMapboxMap() {
        return navigationMapboxMap;
    }

    /**
     * 返回box
     *
     * @return
     */
    public MapboxMap getMapBox() {
        return mapboxMap;
    }

    /**
     * 返回样式
     *
     * @return
     */
    public Style getMapStyle() {
        return style;
    }

    /**
     * 销毁
     */
    public void onDestroy() {
        clearAllLayer();
        style = null;
        mapboxMap = null;
    }

    /**
     * 回到当前位置
     */
    public void jumpCurrentLoc() {
        if (mapboxMap == null)
            return;
        Location location = mapboxMap.getLocationComponent().getLastKnownLocation();
        if (location != null) {
            CameraPosition cameraPosition = new CameraPosition.Builder()
                    .target(new LatLng(39.984487, 116.314541))
//                    .target(new LatLng(39.937771,116.346015))
//                    .target(new LatLng(location.getLatitude(), location.getLongitude()))
                    .build();
            mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
        }
    }


    public void changeMapPaddingBottom(int bottom) {
        if (mapboxMap == null)
            return;
        mapboxMap.animateCamera(CameraUpdateFactory.paddingTo(0, 0, 0, bottom));
    }


    private String MarkerCenterSourceId = "markerCenterSourceid";
    private String MarkerCenterLayerId = "markerCenterLayerid";
    private String MarkerCenterIconId = "markerCenterIconid";


    public void showCenterMarker(Feature feature) {
        if (mapboxMap == null || style == null || feature == null)
            return;
        Source source = style.getSource(MarkerCenterSourceId);
        if (source != null && source instanceof GeoJsonSource) {
            ((GeoJsonSource) source).setGeoJson(feature);
        } else {
            Bitmap bitmap = BitmapFactory.decodeResource(activity.getResources(), R.drawable.map_blue_poi);
            GeoJsonSource geoJsonSource = new GeoJsonSource(MarkerCenterSourceId, FeatureCollection.fromFeature(feature));
            SymbolLayer symbolLayer = new SymbolLayer(MarkerCenterLayerId, MarkerCenterSourceId)
                    .withProperties(
                            iconImage(MarkerCenterIconId)
                            , iconAllowOverlap(true)
                            , iconIgnorePlacement(true)
                            , iconSize(2f)
                            , iconOffset(new Float[]{0f, -9f}));
            style.addImage(MarkerCenterIconId, bitmap);
            style.addSource(geoJsonSource);
            style.addLayer(symbolLayer);
        }
    }

    private String MarkerNearSourceId = "markerNearSourceid";
    private String MarkerNearLayerId = "markerNearLayerid";
    private String MarkerNearIconId = "markerNearIconid";

    /**
     * 清除marker
     */
    public void clearNearMarker() {
        if (style.getLayer(MarkerNearLayerId) != null) {
            style.removeLayer(MarkerNearLayerId);
        }
        if (style.getSource(MarkerNearSourceId) != null) {
            style.removeSource(MarkerNearSourceId);
        }

        if (style.getImage(MarkerNearIconId) != null) {
            style.removeImage(MarkerNearIconId);
        }
    }


    public void showNearMarker(Poi centerPoi, final Poi nearPoi) {
        if (mapboxMap == null || style == null || nearPoi == null)
            return;
        if (centerPoi != null)
            showCenterMarker(centerPoi.toFeature());
        Source source = style.getSource(MarkerNearSourceId);
        Feature feature = nearPoi.toFeature();
        if (source != null && source instanceof GeoJsonSource) {
            ((GeoJsonSource) source).setGeoJson(feature);
        } else {
            Bitmap bitmap = BitmapFactory.decodeResource(activity.getResources(), R.drawable.map_red_poi_m);
            GeoJsonSource geoJsonSource = new GeoJsonSource(MarkerNearSourceId, FeatureCollection.fromFeature(feature));
            SymbolLayer symbolLayer = new SymbolLayer(MarkerNearLayerId, MarkerNearSourceId)
                    .withProperties(
                            iconImage(MarkerNearIconId)
                            , iconAllowOverlap(true)
                            , iconIgnorePlacement(true)
                            , iconSize(1f)
                            , iconOffset(new Float[]{0f, -9f}));
            style.addImage(MarkerNearIconId, bitmap);
            style.addSource(geoJsonSource);
            style.addLayer(symbolLayer);
        }

        if (centerPoi != null) {
            LatLngBounds latLngBounds = new LatLngBounds
                    .Builder()
                    .include(new LatLng(centerPoi.getLat(), centerPoi.getLon()))
                    .include(new LatLng(nearPoi.getLat(), nearPoi.getLon()))
                    .build();
            int left = mWidth / 4 + 100;
            int right = left;
            int top = mHeight / 4 + 150;
            int bottom = top;
            mapboxMap.easeCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, left, top, right, bottom), new MapboxMap.CancelableCallback() {
                @Override
                public void onCancel() {

                }

                @Override
                public void onFinish() {
                    mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(new LatLng(nearPoi.getLat(), nearPoi.getLon())));

                }
            });
        } else {
            mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(new LatLng(nearPoi.getLat(), nearPoi.getLon())));
        }
    }

    /**
     * 清除marker
     */
    public void clearCenterMarker() {
        if (style.getLayer(MarkerCenterLayerId) != null) {
            style.removeLayer(MarkerCenterLayerId);
        }
        if (style.getSource(MarkerCenterSourceId) != null) {
            style.removeSource(MarkerCenterSourceId);
        }

        if (style.getImage(MarkerCenterIconId) != null) {
            style.removeImage(MarkerCenterIconId);
        }
    }


    private String MarkersSourceId = "markerssourceid";
    private String MarkersLayerId = "markerslayerid";
    private String MarkersIconId = "markersiconid";
//    private String SelectMarkerSourceId = "selectmarkersourceid";
//    private String SelectLayerId = "selectlayerid";

    /**
     * 显示多个图标
     *
     * @param list
     */
    public void showMarkers(List<Poi> list) {
        clearMarkers();
        if (list != null && list.size() > 0) {
            List<Feature> featureList = new ArrayList<>();
            LatLngBounds.Builder latLngBounds = new LatLngBounds.Builder();
            for (int i = 0; i < list.size(); i++) {
                Poi poi = list.get(i);
                Feature feature = poi.toFeature();
                featureList.add(feature);
                latLngBounds.include(new LatLng(poi.getLat(), poi.getLon()));
            }
            Bitmap bitmap = BitmapFactory.decodeResource(activity.getResources(), R.drawable.map_red_poi_s);
            GeoJsonSource geoJsonSource = new GeoJsonSource(MarkersSourceId, FeatureCollection.fromFeatures(featureList));
            SymbolLayer symbolLayer = new SymbolLayer(MarkersLayerId, MarkersSourceId)
                    .withProperties(
                            iconImage(MarkersIconId)
                            , iconAllowOverlap(true)
                            , iconIgnorePlacement(true)
                            , iconSize(1f)
                            , iconOffset(new Float[]{0f, -9f}));
            style.addImage(MarkersIconId, bitmap);
            style.addSource(geoJsonSource);
            style.addLayer(symbolLayer);

//            style.addSource(new GeoJsonSource(SelectMarkerSourceId));
//            style.addLayer(new SymbolLayer(SelectLayerId, SelectMarkerSourceId)
//                    .withProperties(PropertyFactory.iconImage(MarkersIconId),
//                            iconAllowOverlap(true),
//                            iconOffset(new Float[]{0f, -9f})));
            if (list.size() > 1)
                //把所有marker显示在一个屏幕里
                mapboxMap.easeCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds.build(), 50, 50, 50, 200));
            else
                jumpPoi(list.get(0));
        }
    }

    /**
     * 清除所有图层
     */
    public void clearAllLayer() {
        clearMarkers();
        clearCenterMarker();
        clearNearMarker();
        if (navigationMapboxMap != null) {
            navigationMapboxMap.clearMarkers();
            navigationMapboxMap.removeRoute();
        }
    }

    /**
     * 清除所有marker
     */
    public void clearMarkers() {
//        if (markerAnimator != null) {
//            markerAnimator.cancel();
//        }
        if (style.getLayer(MarkersLayerId) != null) {
            style.removeLayer(MarkersLayerId);
        }
        if (style.getSource(MarkersSourceId) != null) {
            style.removeSource(MarkersSourceId);
        }

//        if (style.getLayer(SelectLayerId) != null) {
//            style.removeLayer(SelectLayerId);
//        }
//        if (style.getSource(SelectMarkerSourceId) != null) {
//            style.removeSource(SelectMarkerSourceId);
//        }

        if (style.getImage(MarkersIconId) != null) {
            style.removeImage(MarkersIconId);
        }
//        markerSelected = false;
    }

    /**
     * 调转到某个位置
     *
     * @param poi
     */
    public void jumpPoi(Poi poi) {
        if (poi != null && mapboxMap != null) {
            LatLng latLng = new LatLng(poi.getLat(), poi.getLon());
            CameraPosition cameraPosition = new CameraPosition.Builder()
                    .target(latLng)
                    .zoom(17)
                    .build();
            mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
        }
    }

//    private ValueAnimator markerAnimator;
//    private boolean markerSelected = false;


    /**
     * 点击地图获取marker
     *
     * @param point
     * @return
     */
    public Feature selectMapFeature(@NonNull LatLng point) {
        Feature feature = null;
        final SymbolLayer layer =
                (SymbolLayer) style.getLayer(MarkersLayerId);
        PointF pointF = mapboxMap.getProjection().toScreenLocation(point);
        if (layer != null) {
            List<Feature> features = mapboxMap.queryRenderedFeatures(pointF, MarkersLayerId);
            if (!features.isEmpty()) {
                //点击到marker，处理第一个marker
                feature = features.get(0);
                showNearMarker(null, GsonManager.getInstance().parsePoi(feature));
            }
//            final SymbolLayer selectedMarkerSymbolLayer =
//                    (SymbolLayer) style.getLayer(SelectLayerId);
//            if (selectedMarkerSymbolLayer != null) {
//                List<Feature> selectedFeature = mapboxMap.queryRenderedFeatures(
//                        pointF, SelectLayerId);
//
//                if (selectedFeature.size() > 0 && markerSelected) {
//                    return feature;
//                }
//
//                if (features.isEmpty()) {
////                    if (markerSelected) {
////                        markerSelected = false;
//////                        deselectMarker(selectedMarkerSymbolLayer);
////                    }
//                    return feature;
//                }
//
//                GeoJsonSource source = style.getSourceAs(SelectMarkerSourceId);
//                if (source != null) {
//                    source.setGeoJson(FeatureCollection.fromFeatures(
//                            new Feature[]{Feature.fromGeometry(features.get(0).geometry())}));
//                }
//
//                if (markerSelected) {
//                    deselectMarker(selectedMarkerSymbolLayer);
//                }
//                if (features.size() > 0) {
//                    selectMarker(selectedMarkerSymbolLayer);
//                }
//            }
        }

        return feature;
    }

//    /**
//     * 放大选中图标
//     *
//     * @param iconLayer
//     */
//    private void selectMarker(final SymbolLayer iconLayer) {
//        markerAnimator = new ValueAnimator();
//        markerAnimator.setObjectValues(1f, 2f);
//        markerAnimator.setDuration(200);
//        markerAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
//
//            @Override
//            public void onAnimationUpdate(ValueAnimator animator) {
//                iconLayer.setProperties(
//                        PropertyFactory.iconSize((float) animator.getAnimatedValue())
//                );
//            }
//        });
//        markerAnimator.start();
//        markerSelected = true;
//    }

    //    /**
//     * 缩小选中图标
//     */
//    private void deselectMarker(final SymbolLayer iconLayer) {
//        if (markerAnimator != null) {
//            markerAnimator.setObjectValues(2f, 1f);
//            markerAnimator.setDuration(200);
//            markerAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
//
//                @Override
//                public void onAnimationUpdate(ValueAnimator animator) {
//                    iconLayer.setProperties(
//                            PropertyFactory.iconSize((float) animator.getAnimatedValue())
//                    );
//                }
//            });
//            markerAnimator.start();
//            markerSelected = false;
//        }
//    }

    /**
     * 设置导航起终点marker
     */
    public void setDestinationMarker(Point position) {
        if (position != null && navigationMapboxMap != null) {
            navigationMapboxMap.addDestinationMarker(position);
        }
    }

    public void setStartMarker(Point position) {
        if (position != null && navigationMapboxMap != null) {
            navigationMapboxMap.addStartMarker(position);
        }
    }


}
